package org.datavec.linan;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.mortbay.util.ajax.JSON;

import java.util.*;
import java.util.stream.Collectors;

public class infoTreeNode1 {
    private static int nodeNext = 0;
    //第一步获取是否购物的信息熵
    public static void main(String[] args) {
        List<Map<String,String>> initData = initData();
        String classLable = "是否购物";
        String classValue = "是";
        double zEntropy=classEntropy(initData,classLable);


        Map<String,Double> nodeEntropyMap = Maps.newHashMap();
        nodeEntropyMap.put("是否上班",0.0);
        nodeEntropyMap.put("性别",0.0);
        nodeEntropyMap.put("是否结婚",0.0);
         checkTree(initData,nodeEntropyMap,classLable,classValue,"");


//
    }
//    public static void   checkTree(List<Map<String,String>> initData,Map<String,Double> nodeEntropyMap){
////        checkTree(initData,nodeEntropyMap,classLable,classValue,"");
//    }

    public static void checkTree(List<Map<String,String>> initData, Map<String,Double> nodeEntropyMap,String classLable,String classValue,String prentNodeName){
        Map<String,List<TreeNode>> treeNodeMap = Maps.newTreeMap();
        if(nodeEntropyMap.size()>0){
//            if(StringUtils.isNotBlank(prentNodeName)){
//                for(Map<String,String> t:initData){
//                    t.remove(prentNodeName);
//                }
//            }
            double zEntropy=classEntropy(initData,classLable);
            if(zEntropy ==0) {
                return ;
            }

            Map<String,Map<String,TreeNode>> treeMap=Maps.newHashMap();
            for(String nodeName : nodeEntropyMap.keySet()){
                Map<String,TreeNode> nodeEntropy=nodeEntropy(initData,nodeName);
                Map<String,TreeNode> nodeMbEntropy=nodeMbEntropy(initData,nodeEntropy,nodeName,classLable,classValue);
                double entropy = 0.0;
                for(String type : nodeEntropy.keySet()){
                    double nodeSize = nodeEntropy.get(type).getTagSize();
                    double nodeMbSize = 0.0;//数据集中和目标相等的数
                    if(nodeMbEntropy.get(type)!=null){
                        nodeMbSize = nodeMbEntropy.get(type).getTagSize();//数据集中和目标相等的数
                    }

                    if(nodeSize-nodeMbSize != 0){
                        entropy+= nodeSize/initData.size() * (log.log2(nodeMbSize/nodeSize) + log.log2((nodeSize-nodeMbSize)/nodeSize));
                        nodeEntropyMap.put(nodeName, (zEntropy-entropy));
                    }else {
                        nodeEntropyMap.put(nodeName, 0.0);
                    }
                }
                treeMap.put(nodeName,nodeEntropy);
            }
            Map<String,Double>  temp=nodeEntropyMap.entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,(oldValue, newValue) -> oldValue, LinkedHashMap::new));
            String key = null;
            if(nodeNext==0){
                key=temp.keySet().iterator().next();
            }
            List<TreeNode> treeNodes = treeNodeMap.get(key);
            if(treeNodes == null){
                treeNodes = Lists.newArrayList();
            }
            for(String ks:treeMap.get(key).keySet()){
                System.err.print(key+"->"+ks+"-->");
//                System.err.println(ks +"->>>>" + JSON.toString(treeMap.get(key).get(ks).getDatas()));
                treeNodes.add(treeMap.get(key).get(ks));
            }

            for (int i=0;i<treeNodes.size();i++){

                TreeNode node = treeNodes.get(i);
                System.err.print(node.getTagName()+ " --->");
                nodeEntropyMap.clear();
                for(String nodeKey:node.getDatas().get(0).keySet()){
                    if(nodeKey!=key && nodeKey!="姓名" && nodeKey!="是否购物")
                        nodeEntropyMap.put(nodeKey,0.0);

                }
                System.err.println(node.getTagName()+ " --->"+JSON.toString(node.getDatas()));
                checkTree(node.getDatas(),nodeEntropyMap,classLable,classValue,key);
            }
        }

    }
    /**
     * 算出节点占比
     * @param initData
     * @return
     */

    public static Map<String,TreeNode> nodeEntropy(List<Map<String,String>> initData,String nodeName){
        Map<String,TreeNode> treeNodes= new HashMap<>();

        for (Map<String,String > data : initData) {
            String type=data.get(nodeName);
            TreeNode treeNode= TreeNode.getGetTreeNode(treeNodes,type);
            treeNode.setTagSize(treeNode.getTagSize()+1);
            Map<String,String > tdata = new TreeMap<>();
            tdata.putAll(data);
            tdata.remove(nodeName);
            treeNode.setDatas(tdata);
            treeNodes.put(type,treeNode);
        }
        return treeNodes;
    }
    /**
     * 算出节点占比 与墓目标相等比例
     * @param initData
     * @return
     */
    public static  Map<String,TreeNode> nodeMbEntropy(List<Map<String,String>> initData, Map<String,TreeNode> nodeEntropy,String nodeName,String classLable,String classValue){
        Map<String,TreeNode> types= new HashMap<>();
        for(String type : nodeEntropy.keySet()){
            for (Map<String,String > data : initData) {
                if(data.get(classLable).equals(classValue) && data.get(nodeName).equals(type)){
                    TreeNode treeNode= TreeNode.getGetTreeNode(types,type);
                    treeNode.setTagSize(treeNode.getTagSize()+1);
                    treeNode.setDatas(data);
                    types.put(type,treeNode);
                }
            }
        }

        return types;
    }
    /**
     * 信心获取量 看看这个目标的信息熵
     * @return
     */

    public static double classEntropy(List<Map<String,String>> initData,String classLable){
        double entropy= 0.0;
        Map<String,Double> labels=new HashMap<>();
        for (Map<String, String> initDatum : initData) {
            String label=initDatum.get(classLable);
            if(labels.get(label) == null){
                labels.put( label,0.0);
            }
            labels.put( label,labels.get(label)+1);
        }
        for(String lable:labels.keySet()){
            double value=labels.get(lable);
            entropy+=log.log2(value/initData.size());
        }
        return  entropy;
    }

    public static List<Map<String,String>> initData(){
        List<Map<String,String>> datas = new ArrayList<Map<String,String>>();
        Map map = new HashMap();
        map.put("姓名","李楠");
        map.put("是否上班","上班");
        map.put("性别","男");
        map.put("是否结婚","是");
        map.put("是否购物","否");
        datas.add(map);
        map = new HashMap();
        map.put("姓名","李伟");
        map.put("是否上班","上班");
        map.put("性别","男");
        map.put("是否结婚","否");
        map.put("是否购物","是");
        datas.add(map);
        map = new HashMap();
        map.put("姓名","周俊玲");
        map.put("是否上班","上班");
        map.put("性别","女");
        map.put("是否结婚","是");
        map.put("是否购物","是");
        datas.add(map);
        map = new HashMap();
        map.put("姓名","周美");
        map.put("是否上班","上班");
        map.put("性别","男");
        map.put("是否结婚","否");
        map.put("是否购物","否");
        datas.add(map);
        map = new HashMap();
        map.put("姓名","晓光");
        map.put("是否上班","上班");
        map.put("性别","男");
        map.put("是否结婚","是");
        map.put("是否购物","是");
        datas.add(map);
        map = new HashMap();
        map.put("姓名","姜师涛");
        map.put("是否上班","休假");
        map.put("性别","男");
        map.put("是否结婚","否");
        map.put("是否购物","是");
        datas.add(map);
        map = new HashMap();
        map.put("姓名","某女");
        map.put("是否上班","休假");
        map.put("性别","女");
        map.put("是否结婚","是");
        map.put("是否购物","否");
        datas.add(map);
        map = new HashMap();
        map.put("姓名","某女1");
        map.put("是否上班","休假");
        map.put("性别","女");
        map.put("是否结婚","是");
        map.put("是否购物","是");
        datas.add(map);
        map = new HashMap();
        map.put("姓名","某男");
        map.put("是否上班","不上班");
        map.put("性别","男");
        map.put("是否结婚","是");
        map.put("是否购物","否");
        datas.add(map);
        map = new HashMap();
        map.put("姓名","牛方捷");
        map.put("是否上班","不上班");
        map.put("性别","女");
        map.put("是否结婚","是");
        map.put("是否购物","是");
        datas.add(map);
        return datas;
    }

}
